package shortbread;


import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilityPackage;
import ohos.agp.utils.TextTool;
import ohos.app.Context;
import ohos.app.ElementsCallback;
import ohos.bundle.IBundleManager;
import ohos.bundle.ShortcutInfo;
import ohos.global.configuration.Configuration;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Creates app shortcuts from {@code @Shortcut} annotations, {@link #create(Context)} is all that needs to be called.
 *
 * @date 2021/5/27
 */
public final class Shortbread {
    private static Class<?> generated;
    private static Method createShortcuts;
    private static Method callMethodShortcut;
    private static List<List<ShortcutInfo>> totalShortcuts;

    static boolean shortcutsSet;
    static boolean activityLifecycleCallbacksSet;

    private Shortbread() {
    }

    /**
     * Publishes the shortcuts created from activity class annotations and activity method annotations in the project.
     * It will also set an activity lifecycle listener to call an annotated activity method when an activity is started
     * with a method shortcut.
     *
     * @param context Any context, the implementation will use the application context.
     */
    public static void create(Context context) {
        if (generated == null) {
            try {
                generated = Class.forName("shortbread.ShortbreadGenerated");
                createShortcuts = generated.getMethod("createShortcuts", Context.class);
                callMethodShortcut = generated.getMethod("callMethodShortcut", Ability.class);
            } catch (ClassNotFoundException | NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        if (!shortcutsSet) {
            setShortcuts(context);
        }
        if (!activityLifecycleCallbacksSet && context instanceof AbilityPackage) {
            setActivityLifecycleCallbacks((AbilityPackage) context);
        }
        if (context instanceof Ability) {
            callMethodShortcut((Ability) context);
        }
    }

    /**
     * 暂不支持批量创建shortcut.在此提供一个返回所有注解生成的shortCut，供使用者自定义时机创建
     *
     * @return totalShortcuts 所有注解生成的shortcut
     */
    public static List<List<ShortcutInfo>> getTotalShortcuts() {
        return totalShortcuts;
    }

    /**
     * 根据shortcutId创建Shortcut
     *
     * @param context    Context
     * @param shortcutId shortcutId
     */
    public static void createShortcutsById(Context context, String shortcutId) {
        if (totalShortcuts == null || totalShortcuts.size() == 0) {
            return;
        }
        IBundleManager shortcutManager = context.getBundleManager();
        List<ShortcutInfo> enabledShortcuts = totalShortcuts.get(0);
        ShortcutInfo shortcutInfo = null;
        for (int i = 0; i < enabledShortcuts.size(); i++) {
            if (TextTool.isNullOrEmpty(shortcutId)) {
                shortcutInfo = enabledShortcuts.get(0);
                break;
            } else {
                if (TextTool.isEqual(shortcutId, enabledShortcuts.get(i).getId())) {
                    shortcutInfo = enabledShortcuts.get(i);
                    break;
                }
            }
        }
        if (shortcutInfo != null) {
            shortcutManager.addHomeShortcut(shortcutInfo);
        }
    }

    private static void setShortcuts(Context context) {
        IBundleManager shortcutManager = context.getBundleManager();
        if (createShortcuts == null) {
            totalShortcuts = null;
        } else {
            try {
                final Object returnValue = createShortcuts.invoke(generated, context);
                List<List<ShortcutInfo>> shortcuts = (List<List<ShortcutInfo>>) returnValue;
                totalShortcuts = shortcuts;

                List<String> disabledShortcutsIds = new ArrayList<>();
                for (final ShortcutInfo shortcutInfo : shortcuts.get(1)) {
                    disabledShortcutsIds.add(shortcutInfo.getId());
                }
                shortcutManager.disableHomeShortcuts(disabledShortcutsIds);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        shortcutsSet = true;
    }

    private static void setActivityLifecycleCallbacks(AbilityPackage ability) {

        SimpleActivityLifecycleCallbacks callbacks = new SimpleActivityLifecycleCallbacks() {
            private Class<? extends Ability> createdActivityClass;

            @Override
            public void onAbilityStart(Ability ability) {
                super.onAbilityStart(ability);
                createdActivityClass = ability.getClass();
            }

            @Override
            public void onAbilityActive(Ability ability) {
                super.onAbilityActive(ability);
                if (ability.getClass() == createdActivityClass) {
                    callMethodShortcut(ability);
                    createdActivityClass = null;
                }
            }

            @Override
            public void onAbilityForeground(Ability ability) {
                super.onAbilityForeground(ability);
            }
        };
        ElementsCallback elementsCallback = new ElementsCallback() {
            @Override
            public void onMemoryLevel(int i) {
            }

            @Override
            public void onConfigurationUpdated(Configuration configuration) {
            }
        };
        ability.registerCallbacks(callbacks, elementsCallback);
        activityLifecycleCallbacksSet = true;
    }


    private static void callMethodShortcut(Ability ability) {
        if (callMethodShortcut == null || !ability.getIntent().hasParameter("shortbread_method")) {
            return;
        }
        try {
            callMethodShortcut.invoke(generated, ability);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }


}
